<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。
//  JCAT 由中国团队开发维护，是一个国际性的项目。
//  正在使用的这个版本是：0.3.2 / SVN信息：$Id: class.JCAT_FSPreferenceKey.php 1250 2009-02-07 04:53:17Z aleechou $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [HTTP下载] http://jcat.JeCat.cn/download
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.cn/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.cn/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/


/**
 * 文件系统 配置键
 *
 * @author		alee
 * @access		public
 */
class JCAT_FSPreferenceKey implements JCAT_IPreferenceKey
{


	/**
	 * 构造函数
	 * 
	 * @access	public
	 * @param	$sStoreDirectory	string	存储目录
	 * @return	void
	 */
	public function JCAT_FSPreferenceKey(  $sStoreDirectory ) 
	{
		JCAT_ASSERT::ASSERT_DIR($sStoreDirectory)  ;
		JCAT_ASSERT::ASSERT_(is_writable($sStoreDirectory),JCAT_Language::SentenceEx('目录无法写入:%s','JCAT',null,$sStoreDirectory)) ;
		
		$this->sStoreDirectory = JCAT_Global::TidyPath($sStoreDirectory) ;
		
		// 载入 Item
		$sItemDataFile = $this->sStoreDirectory.self::ITEM_DATA_FILENAME ;
		if( is_file($sItemDataFile) )
		{
			$this->bUpdate = false ;
			$this->arrItems = include $sItemDataFile ;
		}
		else
		{
			$this->bUpdate = true ;
			$this->arrItems = array() ;
		}
	}
	
	/**
	 * 析构函数
	 *
	 * @access	public
	 * @return	void
	 */
	public function __destruct()
	{
		// 判断是否已被删除
		if( is_dir($this->sStoreDirectory) )
		{
			$this->Save() ;
		}
	}


	/**
	 * 返回键名称
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetName()
	{
		return basename($this->sStoreDirectory) ;
	}
	
	/**
	 * 保存键
	 *
	 * @access	public
	 * @return	bool
	 */
	public function Save()
	{
		if(!$this->bUpdate)
		{
			return true ;
		}
		
		$sItemDataFile = $this->sStoreDirectory.self::ITEM_DATA_FILENAME ;
		if(!file_put_contents($sItemDataFile,'<? return ' . var_export($this->arrItems,true) .'?>') )
		{
			return false ;
		}
		
		$this->bUpdate = false ;
		return true ;
	}
	

	/**
	 * 删除键
	 *
	 * @access	public
	 * @return	bool
	 */
	public function Delete()
	{
		// 删除子键
		// ... ...
		
		// 删除自己
		if( !JCAT_FSO::DeleteDir($this->sStoreDirectory,true) )
		{
			return false ;
		}
		
		// 清空对象
		$this->arrItems = array() ;
		$this->bUpdate = false ;
		
		return true ;
	}


	/**
	 * 设置一个数据项
	 * 
	 * @access	public
	 * @param	$sItemName		string	数据项名称
	 * @param	$Data			mixed	数据
	 * @return	old_value
	 */
	public function SetItem( $sItemName, $Data ) 
	{
		JCAT_ASSERT::ASSERT_ISTHESE($Data,array('base','array'),JCAT_Language::SentenceEx('JCAT_FSPreferenceKey::SetItem() 只能保存基本数据类型','JCAT',null))  ;
		
		$sName = strval($sItemName) ;
		$this->arrItems[$sName] =& $Data ;
		
		$this->bUpdate = true ;
	}


	/**
	 * 取得数据项数据
	 * 
	 * @access	public
	 * @param	$sItemName		string	数据项名称
	 * @return	mixed
	 */
	public function GetItem(  $sItemName ) 
	{
		return array_key_exists($sItemName,$this->arrItems)?
					$this->arrItems[$sItemName]: null ;
	}



	/**
	 * 删除数据项
	 * 
	 * @access	public
	 * @param	$sItemName		string	数据项名称
	 * @return	bool
	 */
	public function DeleteItem(  $sItemName ) 
	{
		unset($this->arrItems[$sItemName]) ;
		return true ;
	}



	/**
	 * 创建子键
	 * 
	 * @access	public
	 * @param	$sKeyName		string	子键键名
	 * @return	bool
	 */
	public function CreateKey(  $sKeyName ) 
	{
		if( isset($this->arrChildren[$sKeyName]) )
		{
			 return false ;
		}
		
		JCAT_ASSERT::ASSERT_( !in_array($sKeyName,array('.','..')) , JCAT_Language::SentenceEx('非法键名:%s','JCAT',null,$sKeyName))  ;
		JCAT_ASSERT::ASSERT_( !preg_match('/[\/\\"\']/',$sKeyName) , JCAT_Language::SentenceEx('非法键名:%s','JCAT',null,$sKeyName))  ;
		
		$sChildKeyStorePath = $this->sStoreDirectory.$sKeyName ;
		@mkdir($sChildKeyStorePath,0777) ;
		if( !is_dir($sChildKeyStorePath) )
		{
			return false ;
		}
		chmod($sChildKeyStorePath,0777) ;
		
		$this->arrChildren[$sKeyName] = new JCAT_FSPreferenceKey($sChildKeyStorePath) ;
		return $this->arrChildren[$sKeyName] ;
	}



	/**
	 * 取得子键对象
	 * 
	 * @access	public
	 * @param	$sKeyName		string	子键键名
	 * @return	JCAT_IPreferenceKey
	 */
	public function GetKey( $sKeyName ) 
	{
		// 已载入
		if( isset($this->arrChildren[$sKeyName]) )
		{
			return $this->arrChildren[$sKeyName] ;
		}
		
		// 未载入
		else
		{
			// 存在
			if( is_dir($this->sStoreDirectory.$sKeyName) )
			{
				$this->arrChildren[$sKeyName] = new JCAT_FSPreferenceKey($this->sStoreDirectory.$sKeyName) ;
				return $this->arrChildren[$sKeyName] ;
			}
			
			// 不存在
			else
			{
				return null ;
			}
		}
	}



	/**
	 * 删除子键
	 * 
	 * @access	public
	 * @param	$sKeyName		string	子键键名
	 * @return	bool
	 */
	public function DeleteKey(  $sKeyName ) 
	{
		if(!$this->GetKey($sKeyName))
		{
			return false ;
		}
		
		if( !$this->arrChildren[$sKeyName]->Delete() )
		{
			return false ;
		}
		
		unset($this->arrChildren[$sKeyName]) ;
		return true ;
	}


	/**
	 * 返回文件系统路径
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetFSPath()
	{
		return $this->sStoreDirectory ;
	}


	/**
	 * 创建子键迭代器
	 *
	 * @access	public
	 * @return	JCAT_IIterator
	 */
	public function CreateChildKeyIterator()
	{
		return new JCAT_FSPreferenceKeyIterator($this) ;
	}

	/**
	 * 创建数据项迭代器
	 *
	 * @access	public
	 * @return	JCAT_IIterator
	 */
	public function CreateItemIterator()
	{
		return new JCAT_ArrayIterator($this->arrItems) ;		
	}
	
	/**
	 * 以数组形式返回所有Item
	 *
	 * @access	public
	 * @return	array
	 */
	public function GetItems()
	{
		return $this->arrItems ;		
	}
	
	/**
	 * 将所有Item 设置为 以数组形式传入的参数
	 *
	 * @access	public
	 * @param	$arrItems	array
	 * @return	void
	 */
	public function SetItems(array $arrItems)
	{
		$this->arrItems = $arrItems ;
		$this->bUpdate = true ;
	}
	
	
	// 属性 ///////////////////////////////////////////////////////////////////////////////

	/**
	 * What's this Attribute ?
	 * 
	 * @access	private
	 * @var		
	 */
	private $sStoreDirectory ;

	/**
	 * What's this Attribute ?
	 * 
	 * @access	private
	 * @var		
	 */
	private $arrChildren = array() ;

	/**
	 * What's this Attribute ?
	 * 
	 * @access	private
	 * @var		
	 */
	private $arrItems = array() ;

	/**
	 * What's this Attribute ?
	 * 
	 * @access	private
	 * @var		
	 */
	private $bUpdate = false ;

	
	
	const ITEM_DATA_FILENAME = 'inc.items.php' ;
}
?>